package pl.wroc.uni.ii.puzzle.activity;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.restlet.data.MediaType;
import org.restlet.resource.ClientResource;

import pl.wroc.uni.ii.puzzle.R;
import pl.wroc.uni.ii.puzzle.data.DatabaseAdapter;
import pl.wroc.uni.ii.puzzle.data.DateAdapter;
import pl.wroc.uni.ii.puzzle.data.Score;
import pl.wroc.uni.ii.puzzle.game.Game;
import android.app.Activity;
import android.content.Context;
import android.database.SQLException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

public class HighScoresActivity extends Activity {

	@Override
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);	
		setContentView(R.layout.high_scores);
		initTabsLayout();
		new HighScoresLookupTask().execute();
	}

	private void initTabsLayout() {
		
        TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost);
        tabHost.setup();
        tabHost.addTab(tabHost.newTabSpec("myHighScores")
        		.setIndicator("My High Scores",getResources().getDrawable(R.drawable.star))
        		.setContent(R.id.myHighScoreLinearLayout));
        tabHost.addTab(tabHost.newTabSpec("globalHighScores")
        		.setIndicator("Global High Scores",getResources().getDrawable(R.drawable.cup))
        		.setContent(R.id.globalHighScoreLinearLayout));
        tabHost.setCurrentTab(0);        
   	}
	
	private void fillMyHighScoreList(List<Score> scoreList) {
		ListView myHighScoreListView =(ListView)findViewById(R.id.myHighScoreListView);
		ProgressBar myHighScoreProgressBar = (ProgressBar)findViewById(R.id.myHighScoreProgressBar);
		myHighScoreProgressBar.setVisibility(View.GONE);
		fillListViewWithScoreList(myHighScoreListView, scoreList);
	}
	
	private void fillGlobalHighScoreList(List<Score> scoreList) {
		ListView globalHighScoreListView =(ListView)findViewById(R.id.globalHighScoreListView);
		ProgressBar globalHighScoreProgressBar = (ProgressBar)findViewById(R.id.globalHighScoreProgressBar);
		globalHighScoreProgressBar.setVisibility(View.GONE);
		fillListViewWithScoreList(globalHighScoreListView, scoreList);
	}

	private void fillListViewWithScoreList(ListView listView, List<Score> scoreList) {
		ScoreAdapter scoreAdapter = new ScoreAdapter(this, scoreList);
		listView.setAdapter(scoreAdapter);
		listView.refreshDrawableState();
	}

	private List<Score> retrieveMyHighScore() {
		DatabaseAdapter databaseAdapter = new DatabaseAdapter(this);
		List<Score> scores = null;
		try {
			databaseAdapter.open();
			scores = databaseAdapter.getHighScores();
			databaseAdapter.close();
		} catch (SQLException e) {
			Log.e(HighScoresActivity.class.getName(), "can't receive data from base", e);
			showToast(getString(R.string.canNotReceiveDataFromBase));
		}
		return (scores != null) ? scores : new LinkedList<Score>();
	}
	
	private List<Score> retrieveGlobalHighScore() {
		ClientResource cr = new ClientResource(Game.PUZZLE_WS_ADDRESS);
		GsonBuilder gsonb = new GsonBuilder();
		gsonb.registerTypeAdapter(Date.class, new DateAdapter());
		Gson gson = gsonb.create();
		List<Score> scores = null;
		try {
			String scoresString = cr.get(MediaType.APPLICATION_JSON).getText();
			scores = gson.fromJson(scoresString, new TypeToken<List<Score>>(){}.getType());
		} catch (Exception e) {
			Log.e(HighScoresActivity.class.getName(), "can't receive data from server", e);
			showToast(getString(R.string.canNotReceiveDataFromServer));
		}
		return (scores != null) ? scores : new LinkedList<Score>();
	}
	
	private void showToast(final String message) {
		runOnUiThread(new Runnable() {
			@Override
		    public void run() {
		    	Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
		    }
		});
	}
	
	private class HighScoresLookupTask extends AsyncTask <Void, List<Score>, List<Score>> {
		
		@SuppressWarnings("unchecked")
		@Override
		protected List<Score> doInBackground(Void... params) {
			List<Score> scores = retrieveMyHighScore();
			publishProgress(scores);
			return retrieveGlobalHighScore();
		}
		
		@Override
		protected void onProgressUpdate(List<Score>... scores) {
			super.onProgressUpdate(scores);
			fillMyHighScoreList(scores[0]);
		}

		@Override
		protected void onPostExecute(List<Score> scores) {
			super.onPostExecute(scores);
			fillGlobalHighScoreList(scores);
		}
	}
	
	private class ScoreAdapter extends BaseAdapter {
	    private LayoutInflater inflater;
	    private SimpleDateFormat dateFormat;
	    private List<Score> scores;
	 
	    public ScoreAdapter(Context context, List<Score> list) {
	        inflater = LayoutInflater.from(context);
	        dateFormat = new SimpleDateFormat("dd/mm/yyyy");
	        this.scores = list;
	    }
	 
	    public View getView(int position, View convertView, ViewGroup parent) {
	        if (convertView == null) {
	            convertView = inflater.inflate(R.layout.scores_list_item, parent, false);
	        }
	        TextView positionTextView = (TextView) convertView.findViewById(R.id.positionTextView);
	        TextView scoreTextView = (TextView) convertView.findViewById(R.id.scoreTextView);
	        TextView userNameTextView = (TextView) convertView.findViewById(R.id.userNameTextView);
	        TextView hardshipTextView = (TextView) convertView.findViewById(R.id.hardshipTextView);
	        TextView dateTextView = (TextView) convertView.findViewById(R.id.dateTextView);
	 
	        Score score = scores.get(position);
	        positionTextView.setText(String.valueOf(position+1)); //+1 becouse high scores should start with 1, not 0
	        scoreTextView.setText(String.valueOf(score.getScore()));
	        userNameTextView.setText(String.valueOf(score.getName()));
	        hardshipTextView.setText(String.valueOf(score.getHardship()));
	        dateTextView.setText(String.valueOf(dateFormat.format(score.getDate())));
	        
	        return convertView;
	    }
	 
	    public int getCount() {
	        return scores.size();
	    }
	 
	    public Object getItem(int arg0) {
	        return scores.get(arg0);
	    }
	 
	    public long getItemId(int arg0) {
	        return arg0;
	    }
	}
	
}
